﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MossmanMill.DataModel;
using System.Windows.Forms.DataVisualization.Charting;

namespace MossmanMill.View
{
    public partial class SearchForm : Form
    {

        private List<Card> cards;
        private List<Rack> racks;
        private IDatabaseAccess db;
        private Object selection; //Either a card or Rack, used for drawing and more

        private MainForm mainform;

        private enum SearchType
        {
            Card, //Sensor channels
            Rack //Card slots
        }

        private SearchType searchType;

        public SearchForm(MainForm mainform)
        {
            this.mainform = mainform;
            InitializeComponent();
            searchType = SearchType.Rack;
            var dbFactory = new DBFactory();
            db = dbFactory.Make(DBFactory.CLASS_TYPE_DATABASE);
            setupChart();
            cards = db.GetCards();
            racks = db.GetRacks();
            CardTypeFilter.Items.Clear();
            CardTypeFilter.Items.Add("Any");
            CardTypeFilter.Items.Add(CardType.DI);
            CardTypeFilter.Items.Add(CardType.DO);
            CardTypeFilter.Items.Add(CardType.AI);
            CardTypeFilter.Items.Add(CardType.AO);
            CardTypeFilter.Items.Add(CardType.OTHER);
            CardTypeFilter.SelectedIndex = 0;
        }

        private void setupChart()
        {
            graph.Series.Clear();
            var racks = db.GetRacks();
            var rackLblSeries = graph.Series.Add("Rack Labels");
            var rackSeries = graph.Series.Add("Rack Free Space");
            var cardSeries = graph.Series.Add("Card Free Space");
            var cardSeries2 = graph.Series.Add("Card Utilization");
            rackSeries.ChartType = SeriesChartType.Bar;
            rackLblSeries.ChartType = SeriesChartType.Bar;
            cardSeries.ChartType = SeriesChartType.Bar;
            cardSeries2.ChartType = SeriesChartType.Bar;
            foreach (var rack in racks)
            {
                var point = rackLblSeries.Points.Add(0);
                point.Label = rack.ToString() + " " + rack.Room.Name;
                rackSeries.Points.Add(rack.GetFreeSlots());
                int freeSpace = 0;
                int totalSpace = 0;
                foreach (var card in rack.Cards) 
                    if (card is Card)
                    {
                        freeSpace += ((Card)card).GetFreeChannels();
                        totalSpace += ((Card)card).GetChannels();
                    }
                cardSeries.Points.Add(freeSpace);
                var usage = (int)((float)(totalSpace - freeSpace) / (float)totalSpace * 13f);
                cardSeries2.Points.Add(usage);
            }
        }

        private void ToggleSearch(object sender, EventArgs e)
        {
            SearchType type = searchType;
            searchType = sender == this.channelRdo ? SearchType.Card : SearchType.Rack;
            bool slot = searchType == SearchType.Rack;
            this.channelRdo.Checked = !slot;
            this.cardRdo.Checked = slot;
            CardTypeFilter.Visible = !slot;
            typeLbl.Visible = !slot;
            this.slotTarget.Maximum = searchType == SearchType.Rack ? 13 : 100;
            
            if (type == searchType) return;
            Filter(sender, e);
        }

        private void Filter(object sender, EventArgs e)
        {
            int target = (int)this.slotTarget.Value;
            switch (searchType)
            {
                case SearchType.Card:
                    resultList.Items.Clear();
                    foreach (Card card in cards) {
                        if (CardTypeFilter.SelectedItem is CardType)
                        {
                            var type = (CardType) CardTypeFilter.SelectedItem;
                            if (card.Type != type) continue;
                        }
                        if (card.GetFreeChannels() >= target)
                        {
                            var item = new ListViewItem(card.ToString());
                            item.Tag = card;
                            resultList.Items.Add(item);
                        }
                    }
                    break;
                case SearchType.Rack:
                    resultList.Items.Clear();
                    foreach (Rack rack in racks)
                    {
                        if (rack.GetFreeSlots() >= target)
                        {
                            var item = new ListViewItem(rack.ToString());
                            item.Tag = rack;
                            resultList.Items.Add(item);
                        }
                    }
                    break;
            }
        }

        private void SelectItem(object sender, EventArgs e)
        {
            if (resultList.SelectedItems.Count == 0)
            {
                rackBrowserBtn.Enabled = false;
                rackInputBtn.Enabled = false;
                rackPlannerBtn.Enabled = false;
                return;
            }
            var tag = resultList.SelectedItems[0].Tag;
            selection = tag;
            if (selection is IDrawable)
            {
                rackBrowserBtn.Enabled = true;
                rackInputBtn.Enabled = true;
                rackPlannerBtn.Enabled = true;
            }
            drawPanel.Invalidate();
        }

        private void OnDraw(object sender, PaintEventArgs e)
        {
            if (selection == null) return;
            if (selection is Rack)
            {
                var rack = (Rack)selection;
                e.Graphics.DrawString(rack.Room.Name, Fonts.smallArial, Brushes.Black, 20, 0);
                rack.draw(e.Graphics, 20, 20);
            }
            if (selection is Card)
            {
                var card = (Card)selection;
                e.Graphics.DrawString(card.Rack.Room.Name, Fonts.smallArial, Brushes.Black, 20, 0);
                e.Graphics.DrawString(card.Rack.ToString(), Fonts.smallArial, Brushes.Black, 140, 0);
                card.draw(e.Graphics, 20, 20, 1f, true);
                var s = card.SelectedSensor;
                if (s != null) card.draw(e.Graphics, 20, 20);
            }
        }

        private void ClickComponent(object sender, MouseEventArgs e)
        {
            if (selection is IDrawable)
            {
                var drawable = (IDrawable)selection;
                drawable.interact(e.Location, 2, 20, 20, 1f, true);
                drawPanel.Invalidate();
            }
        }

        private void SearchForm_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 'honeywellRacksDataSet.Rack' table. You can move, or remove it, as needed.
            this.rackTableAdapter.Fill(this.honeywellRacksDataSet.Rack);

        }

        private void rackPlannerBtn_Click(object sender, EventArgs e)
        {
            if (selection == null) return;
            RackPlanner.RackPlanner form = new RackPlanner.RackPlanner(mainform);
            if (selection is Card) form.LoadCard((Card)selection);
            if (selection is Rack) form.LoadRack((Rack)selection);
            form.Show();
        }

        private void rackInputBtn_Click(object sender, EventArgs e)
        {
            if (selection == null) return;
            DataInputForm form = new DataInputForm();
            if (selection is Card) form.LoadCard((Card)selection);
            if (selection is Rack) form.LoadRack((Rack)selection);
            form.Show();
        }

        private void rackBrowserBtn_Click(object sender, EventArgs e)
        {
            if (selection == null) return;
            if (selection is Card) mainform.LoadCard((Card)selection);
            if (selection is Rack) mainform.LoadRack((Rack)selection);
            mainform.Invalidate();
            this.Close();
        }

    }
}
